﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Threading;

namespace StockTrader.QuoteCenter.Streamer.BLL
{
    public class ClientManager
    {
        private static readonly object oLocker = new object();
        private static ClientManager instance;
        public static ClientManager Instance
        {
            get
            {
                if (instance == null)
                    lock(oLocker)
                    {
                        if (instance == null)
                        {
                            var temp = new ClientManager();
                            Thread.MemoryBarrier();
                            instance = temp;
                        }
                    }
                return instance;
            }
        }
        private List<AsyncCallbacksWapper> oListOfCallBacks = new List<AsyncCallbacksWapper>();

        public ClientManager()
        {
            // Register for the update
            DataAdapter.OnStocksChanged += new DataAdapter.StocksChangedDeleaget(onStockChange);
        }
        private void onStockChange(StocksEventArgs args)
        {
            List<AsyncCallbacksWapper> asyncCallbacksWrapperTemp;
            lock(oLocker)
            {
                asyncCallbacksWrapperTemp = new List<AsyncCallbacksWapper>(this.oListOfCallBacks);
                this.oListOfCallBacks.Clear();
            }

            foreach (var callback in asyncCallbacksWrapperTemp)
            {
                if (!callback.AsyncResult.IsCompleted)
                {
                    callback.AsyncResult.SetAsCompeleted(args.stock, false);
                }
            }
        }

        public void AddCallBack(AsyncCallbacksWapper oCallBack)
        {
            lock (oLocker)
            {
                //If already exists must invoke it and reinsert it (instead of removig it on timeouts)
                var oAsyncCallbacksWrapperTemp =
                    GetAsyncCallbacksWrapperBySessionID(oCallBack.SessionID);

                if (oAsyncCallbacksWrapperTemp == null)
                {
                    this.oListOfCallBacks.Add(oCallBack);
                }
                else
                {
                    //It's not null. must invoke it
                    this.oListOfCallBacks.Remove(oAsyncCallbacksWrapperTemp);
                    this.oListOfCallBacks.Add(oCallBack);
                }
            }
        }

        public AsyncCallbacksWapper GetAsyncCallbacksWrapperBySessionID(string sSessionID)
        {
            foreach (AsyncCallbacksWapper oAsyncCallbacksWrapper in this.oListOfCallBacks)
            {
                if (oAsyncCallbacksWrapper.SessionID == sSessionID)
                {
                    return oAsyncCallbacksWrapper;
                }
            }
            return null;
        }
    }
}
